
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_SIGNED.ALL;

ENTITY  Execute IS
	PORT(	Read_data_1			: IN 	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
			Read_data_2			: IN 	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
			Sign_extend			: IN 	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
			Function_opcode		: IN 	STD_LOGIC_VECTOR( 5 DOWNTO 0 );
			ALUOp				: IN 	STD_LOGIC_VECTOR( 1 DOWNTO 0 );
			ALUSrc				: IN 	STD_LOGIC;
			Zero				: OUT	STD_LOGIC;
			ALU_Result			: OUT	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
			Add_Result			: OUT	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
			PC_plus_4			: IN 	STD_LOGIC_VECTOR( 7 DOWNTO 0 );
			clock, reset		: IN 	STD_LOGIC );
END Execute;

ARCHITECTURE behavior OF Execute IS
SIGNAL Ainput, Binput 			: STD_LOGIC_VECTOR( 7 DOWNTO 0 );
SIGNAL ALU_output_mux			: STD_LOGIC_VECTOR( 7 DOWNTO 0 );
SIGNAL Branch_Add 				: STD_LOGIC_VECTOR( 7 DOWNTO 0 );--was 8 DOWNTO 0
SIGNAL ALU_ctl					: STD_LOGIC_VECTOR( 2 DOWNTO 0 );
BEGIN
	Ainput <= Read_data_1;
	-- ALU entrada do mux
	Binput <= Read_data_2 
		WHEN ( ALUSrc = '0' ) 
  		ELSE  Sign_extend( 7 DOWNTO 0 );
	-- bits de controle da ALU
	ALU_ctl( 0 ) <= ( Function_opcode( 0 ) OR Function_opcode( 3 ) ) AND ALUOp(1 );
	ALU_ctl( 1 ) <= ( NOT Function_opcode( 2 ) ) OR (NOT ALUOp( 1 ) );
	ALU_ctl( 2 ) <= ( Function_opcode( 1 ) AND ALUOp( 1 )) OR ALUOp( 0 );
	-- flag Zero
	Zero <= '1' 
		WHEN ( ALU_output_mux( 7 DOWNTO 0 ) = "00000000"  )
		ELSE '0';    
	-- seleciona saida da ALU        
	ALU_result	<= "0000000"  & ALU_output_mux( 7 ) 
		WHEN  ALU_ctl = "111" 
		ELSE  	ALU_output_mux( 7 DOWNTO 0 );
	-- adiciona para incrementar o branch
	Branch_Add	<= PC_plus_4( 7 DOWNTO 2 ) +  Sign_extend( 7 DOWNTO 0 ) ;
	Add_result	<= Branch_Add( 7 DOWNTO 0 );

PROCESS ( ALU_ctl, Ainput, Binput )
	BEGIN
					-- selecao da operacao da ALU
 	CASE ALU_ctl IS
		-- operacao logica AND
		WHEN "000" 	=>	ALU_output_mux 	<= Ainput AND Binput; 
		-- operacao logica OR
     	WHEN "001" 	=>	ALU_output_mux 	<= Ainput OR Binput;
		-- ALUresult = A + B
	 	WHEN "010" 	=>	ALU_output_mux 	<= Ainput + Binput;
		-- ALU executa SLT
 	 	WHEN "011" 	=>	ALU_output_mux 	<= Ainput - Binput;
		-- operacao logica XOR
 	 	WHEN "100" 	=>	ALU_output_mux 	<= Ainput XOR Binput;
		-- operacao logica XOR
 	 	WHEN "101" 	=>	ALU_output_mux 	<= Ainput NOR Binput;
		-- ALUresult = A_input -B_input
 	 	WHEN "110" 	=>	ALU_output_mux 	<= Ainput - Binput;
		-- ALU executa SLT
  	 	WHEN "111" 	=>	ALU_output_mux 	<= "00000000" ;
 	 	WHEN OTHERS	=>	ALU_output_mux 	<= "00000000" ;
  	END CASE;
  END PROCESS;
END behavior;

